import time
from datetime import datetime, timedelta

from flask import current_app
from flask import g
from flask import render_template, jsonify
from flask import request, redirect
from flask import session

from info import constants, db
from info import user_login_data
from info.models import User, News, Category
from info.modules.admin import admin
from info.response_code import RET
from info.utils.image_storage import image_storage


@admin.route('/add_category', methods=['POST'])
def add_category():
    # 获取参数
    id = request.json.get('id')
    name = request.json.get('name')

    # 校验参数
    if not name:
        return jsonify(errno=RET.NODATA, errmsg='参数不全')

    # 判断有误id
    if not id:
        # 增加
        category = Category()
        category.name = name

        try:
            db.session.commit()
            db.session.add(category)
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg='保存异常')
    else:
        # 修改
        try:
            category = Category.query.get(id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='操作失败')

        if not category:
            return jsonify(errno=RET.NODATA, errmsg='菜单获取失败')

        category.name = name

    return jsonify(errno=RET.OK, errmsg='操作成功!')


@admin.route('/news_category')
def news_category():
    # 获取所有的菜单
    try:
        categories = Category.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询异常')
    if not categories:
        return jsonify(errno=RET.NODATA, errmsg='获取失败')

    return render_template('admin/news_type.html', categories=categories)


@admin.route('/news_edit_detail', methods=['GET', 'POST'])
def news_edit_detail():
    # get 请求显示新闻数据
    if request.method == 'GET':
        # 获取参数
        news_id = request.args.get('news_id')
        # 校验参数
        if not news_id:
            return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
        # 查询查询
        try:
            news = News.query.get(news_id)
            category = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询异常')
        # 返回响应
        return render_template('admin/news_edit_detail.html', news=news.to_dict(), category=category)
    # post 请求 执行操作
    # news_id, title, digest, content, index_image, category_id
    # 获取参数
    news_id = request.form.get('news_id')
    title = request.form.get('title')
    digest = request.form.get('digest')
    content = request.form.get('content')
    index_image = request.files.get('index_image')
    category_id = request.form.get('category_id')

    # 校验参数
    if not all([news_id, title, digest, content, index_image, category_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 获取新闻对象
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取新闻失败')

    # 校验新闻对象
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='新闻不存在')

    # 上传图片
    try:
        img_name = image_storage(index_image.read())
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='七牛云失败!')

    if not img_name:
        return jsonify(errno=RET.NODATA, errmsg='图片上传失败')

    news.content = content
    news.category_id = category_id
    news.digest = digest
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + img_name
    news.title = title

    return jsonify(errno=RET.OK, errmsg='操作成功!')


@admin.route('/news_edit')
def news_edit():
    """
    新闻编辑

    1.获取参数
    2.对参数做类型转化
    3.判断可选参数是否存在
    4.动态拼接参数
    5.分页查询
    6.拼接参数
    7.返回响应
    :return:
    """
    # 1.获取参数
    page = request.args.get('p', 1)
    keyword = request.args.get('keyword')

    # 2.对参数做类型转化
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    # 3.判断可选参数是否存在
    filters = [News.status == 0]
    if keyword:
        filters.append(News.title.contains(keyword))
    # 4.动态拼接参数

    # 5.分页查询
    try:
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page,
                                                                                          constants.ADMIN_NEWS_PAGE_MAX_COUNT,
                                                                                          False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询异常')
    # 6.拼接参数
    news_list = []
    for item in paginate.items:
        news_list.append(item.to_review_dict())
    data = {
        'totalPage': paginate.pages,
        'currentPage': paginate.page,
        'news_list': news_list

    }

    # 7.返回响应
    return render_template('admin/news_edit.html', data=data)


@admin.route('/news_review_detail', methods=['GET', 'POST'])
def news_review_detail():
    # GET 请求
    if request.method == 'GET':
        # 获取参数
        news_id = request.args.get('news_id')
        # 校验参数
        if not news_id:
            return jsonify(errno=RET.PARAMERR, errmsg='参数异常')
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询异常')

        if not news:
            return jsonify(errno=RET.NODATA, errmsg='新闻不存在')
        # 返回响应
        return render_template('admin/news_review_detail.html', news=news.to_dict())
    # POST 请求
    # 获取参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    reason = request.json.get('reason')
    # 校验参数
    if not action:
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
    # 判断参数是否在范围中
    if action not in ['accept', 'reject']:
        return jsonify(errno=RET.PARAMERR, errmsg='参数有误')
    if not news_id:
        return jsonify(errno=RET.PARAMERR, errmsg='参数异常')
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询异常')

    if not news:
        return jsonify(errno=RET.NODATA, errmsg='新闻不存在')

    # 根据不同的操作类型执行不同的
    if action == 'accept':
        news.status = 0
    else:
        news.status = -1

    # 返回响应
    return jsonify(errno=RET.OK, errmsg='操作成功!')


@admin.route('/news_review')
def news_review():
    """
    获取新闻审核
    1.获取参数
    2.参数转换
    3.分页查询
    4.凭借参数
    5.转换成字典对象
    6.返回响应
    :return:
    """

    # 1.获取参数
    page = request.args.get('p', 1)
    keyword = request.args.get('keyword')
    # 2.参数转换
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    filters = [News.status != 0]
    if keyword:
        filters.append(News.title.contains(keyword))
    # 3.分页查询
    try:
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page,
                                                                                          constants.ADMIN_NEWS_PAGE_MAX_COUNT,
                                                                                          False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询异常')

    # 4.凭借参数
    currentPage = paginate.page
    totalPage = paginate.pages
    items = paginate.items

    # 5.转换成字典对象
    news_list = []
    for item in items:
        news_list.append(item.to_review_dict())

    # 6.返回响应
    data = {
        'currentPage': currentPage,
        'totalPage': totalPage,
        'news_list': news_list
    }

    return render_template('admin/news_review.html', data=data)


@admin.route('/user_list')
@user_login_data
def user_list():
    """
    查询列表

    1.获取参数
    2.参数转换
    3.分页查询
    4.凭借参数
    5.转换成字典对象
    6.返回响应
    :return:
    """

    # 1.获取参数
    page = request.args.get('p', 1)

    # 2.参数转换
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 3.分页查询
    try:
        paginate = User.query.filter(User.is_admin != True).paginate(page, constants.ADMIN_USER_PAGE_MAX_COUNT, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询失败')

    # 4.凭借参数
    currentPage = paginate.page
    totalPage = paginate.pages
    items = paginate.items

    # 5.转换成字典对象
    user_list = []
    for user in items:
        user_list.append(user.to_admin_dict())

    data = {
        'currentPage': currentPage,
        'totalPage': totalPage,
        'user_list': user_list
    }
    # 6.返回响应

    return render_template('admin/user_list.html', data=data)


@admin.route('/user_count')
@user_login_data
def user_count():
    """
       1.查询所有用户总人数
       2.当前月活人数
       3.当天活跃
       :return:
       """
    # 获取所有用户人书
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询用户失败')

    # 获取月活人数
    try:
        # 获取日历对象
        cal = time.localtime()
        # 获取到本月的1号字符串
        month_start_str = "%d-%d-01" % (cal.tm_year, cal.tm_mon)
        # 将本月1号的字符串转成日期对象
        month_start_date = datetime.strptime(month_start_str, "%Y-%m-%d")

        # 查询月活人数
        month_count = User.query.filter(User.last_login >= month_start_date).count()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询失败')

    # 查询日活跃
    try:
        # 获取日历对象
        cal = time.localtime()
        # 获取到本日的00:00字符串
        day_start_str = "%d-%d-%d" % (cal.tm_year, cal.tm_mon, cal.tm_mday)
        # 将本月1号的字符串转成日期对象
        day_start_date = datetime.strptime(day_start_str, "%Y-%m-%d")

        # 查询月活人数
        day_count = User.query.filter(User.last_login >= day_start_date).count()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询失败')
        # 4.活跃日期所对应的活跃人数
    active_date = []  # 活跃的时间段
    active_count = []  # 活跃人数
    for i in range(0, 31):
        # 当天开始时间A
        begin_date = day_start_date - timedelta(days=i)
        # 当天开始时间, 的后一天B
        end_date = day_start_date - timedelta(days=i - 1)

        # 添加当天开始时间字符串到, 活跃日期中
        active_date.append(begin_date.strftime("%Y-%m-%d"))

        # 查询时间A到B这一天的注册人数
        everyday_active_count = User.query.filter(User.is_admin == False, User.last_login >= begin_date,
                                                  User.last_login <= end_date).count()

        # 添加当天注册人数到,获取数量中
        active_count.append(everyday_active_count)

    # 反转
    active_date.reverse()
    active_count.reverse()

    # 5.拼接数据渲染页面
    data = {
        "total_count": total_count,
        "month_count": month_count,
        "day_count": day_count,
        "active_date": active_date,
        "active_count": active_count
    }
    return render_template('admin/user_count.html', data=data)


@admin.route('/logout', methods=['DELETE'])
def logout():
    # 清除session信息
    session.pop("user_id", None)
    session.pop("nick_name", None)
    session.pop("mobile", None)
    session.pop("is_admin", None)

    return jsonify(errno=RET.OK, errmsg="退出成功")


@admin.route('/index')
@user_login_data
def index():
    data = {
        'userInfo': g.user.to_dict() if g.user else ''
    }

    return render_template('admin/index.html', data=data)


@admin.route('/login', methods=['GET', 'POST'])
def login():
    """
    显示用户登陆页面
    :return:
    """

    if request.method == 'GET':
        if session.get('is_admin') and session.get('user_id'):
            return redirect('/admin/index')
        return render_template('admin/login.html')

    # 从form获取参数
    username = request.form.get('username')
    password = request.form.get('password')

    # 校验参数
    if not all([username, password]):
        return render_template('admin/login.html', errno=RET.PARAMERR, errmsg='参数异常')

    # 判断是否是管理员用户
    try:
        user = User.query.filter(User.mobile == username, User.is_admin == True).first()
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/login.html', errno=RET.DBERR, errmsg='查询失败')

    # 判断用户是否是管理员用户
    if not user:
        return render_template('admin/login.html', errno=RET.NODATA, errmsg='用户获取失败')

    # 校验密码
    if not user.check_passowrd(password):
        return render_template('admin/login.html', errno=RET.DATAERR, errmsg='密码错误')

    # 保存数据在session中
    session["user_id"] = user.id
    session["nick_name"] = user.nick_name
    session["mobile"] = user.mobile
    session["is_admin"] = True
    # 重定向到首页
    return redirect('/admin/index')
